//
//  UIView+Extension.swift
//  Skeleton
//
//  Created by bin hu on 2025/6/4.
//

import UIKit

private struct SkeletonConstants {
    static let baseZPosition: CGFloat = 1000
    static let depthFactor: CGFloat = 0.8
    static let cornerRadius: CGFloat = 4
    static let animationDuration: TimeInterval = 1.8
    static let highlightColor = UIColor(white: 0.97, alpha: 1)
    static let baseColor = UIColor(white: 0.90, alpha: 1)
}

private struct Constants {
    static let baseZPosition: CGFloat = 1000
    static let depthFactor: CGFloat = 0.8
    static let cornerRadius: CGFloat = 4
    static let animationDuration: TimeInterval = 1.5
    static let highlightColor = UIColor(white: 0.97, alpha: 1)
    static let baseColor = UIColor(white: 0.90, alpha: 1)
}

private var skeletonLayersKey: UInt8 = 0
private var excludedViewsKey: UInt8 = 0
private var layerPoolKey: UInt8 = 0
private var skeletonEnableKey: UInt8 = 0

extension UIView {
    
//    @IBInspectable
    /// 控制骨架屏启用的布尔属性
    var skeletonEnable: Bool {
        get {
            return objc_getAssociatedObject(self, &skeletonEnableKey) as? Bool ?? false
        }
        set {
            objc_setAssociatedObject(self, &skeletonEnableKey, newValue, .OBJC_ASSOCIATION_RETAIN)
            if newValue {
                showSkeleton()
            }else{
                hideSkeleton()
            }
        }
    }

    private var skeletonLayers: [String: CALayer] {
        get { objc_getAssociatedObject(self, &skeletonLayersKey) as? [String: CALayer] ?? [:] }
        set { objc_setAssociatedObject(self, &skeletonLayersKey, newValue, .OBJC_ASSOCIATION_RETAIN) }
    }
    
    private var excludedViews: Set<UIView> {
        get { objc_getAssociatedObject(self, &excludedViewsKey) as? Set<UIView> ?? [] }
        set { objc_setAssociatedObject(self, &excludedViewsKey, newValue, .OBJC_ASSOCIATION_RETAIN) }
    }
    
    private var layerPool: SkeletonLayerPool {
        get {
            if let pool = objc_getAssociatedObject(self, &layerPoolKey) as? SkeletonLayerPool {
                return pool
            }
            let newPool = SkeletonLayerPool()
            objc_setAssociatedObject(self, &layerPoolKey, newPool, .OBJC_ASSOCIATION_RETAIN)
            return newPool
        }
    }
    
    func showSkeleton() {
        removeAllSkeletons()
        addSkeletonsRecursively(for: self)
        startAnimations()
    }
    
    func hideSkeleton() {
        stopAnimations()
        removeAllSkeletons()
    }
    
    func excludeSkeletonView(_ view: UIView) {
        excludedViews.insert(view)
    }
    
    /// 跳过排除的视图和隐藏视图
    private func addSkeletonsRecursively(for view: UIView) {
        guard !excludedViews.contains(view),
              !view.isHidden,
              view.alpha > 0.01,
              view.frame.width > 0 && view.frame.height > 0 else {
            return
        }
        
        let depth = viewDepth(view)
        let zPosition = SkeletonConstants.baseZPosition + depth * SkeletonConstants.depthFactor
        let identifier = "\(ObjectIdentifier(view).hashValue)"
        
        addSkeletonLayer(for: view, identifier: identifier, zPosition: zPosition)
        
        /// 递归处理所有可见子视图
        for subview in view.subviews {
            addSkeletonsRecursively(for: subview)
        }
    }
    
    private func viewDepth(_ view: UIView) -> CGFloat {
        var depth: CGFloat = 0
        var current: UIView? = view.superview
        while current != nil {
            depth += 1
            current = current?.superview
        }
        return depth
    }
    
    private func addSkeletonLayer(for view: UIView, identifier: String, zPosition: CGFloat) {
        // 确保视图在视图层级中
        guard view.superview != nil else { return }
        
        let frame = view.convert(view.bounds, to: self)
        // 跳过无效或不可见的frame
        guard !frame.isInfinite, !frame.isNull,
              frame.width > 0, frame.height > 0,
              frame.maxX > 0, frame.maxY > 0 else {
            return
        }
        
        let skeletonLayer = layerPool.dequeueLayer()
        configureSkeletonLayer(skeletonLayer,
                               frame: frame,
                               depth: zPosition,
                               view: view)
        skeletonLayer.zPosition = zPosition
        layer.addSublayer(skeletonLayer)
        skeletonLayers[identifier] = skeletonLayer
    }
    
    private func configureSkeletonLayer(_ layer: CALayer,
                                        frame: CGRect,
                                        depth: CGFloat,
                                        view:UIView) {

        layer.frame = frame
        
        let depthFactor = min(1.0, max(0.2, (depth - Constants.baseZPosition) / 100))
        let baseColor = Constants.baseColor.withBrightnessDelta(-depthFactor * 0.1)
        let highlight = Constants.highlightColor.withBrightnessDelta(-depthFactor * 0.1)
        
        if let gradientLayer = layer as? CAGradientLayer {
            gradientLayer.colors = [baseColor.cgColor, highlight.cgColor, baseColor.cgColor]
            gradientLayer.drawsAsynchronously = true
            gradientLayer.locations = [0, 0.5, 1]
            gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
            gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
        }
        
        layer.cornerRadius = Constants.cornerRadius - depthFactor * 2 // view.layer.cornerRadius
        layer.masksToBounds = true
    }
    
//    private func configureSkeletonLayer(_ layer: CALayer, frame: CGRect, depth: CGFloat, view: UIView) {
//        layer.frame = frame
//        
//        let depthFactor = min(1.0, max(0.2, (depth - Constants.baseZPosition) / 100))
//        
//        // 1. 增强颜色对比度 - 使用更极端的亮度调整
//        let baseDarkening: CGFloat = 0.3  // 基础色加深60%
//        let highlightBrightening: CGFloat = 0.5  // 高光色增亮80%
//        let saturationBoost: CGFloat = 0.2  // 增加饱和度增强效果
//        
//        var baseColor = Constants.baseColor
//        var highlight = Constants.highlightColor
//        
//        // 增加饱和度提升视觉区分度
//        baseColor = baseColor.withSaturationDelta(depthFactor * saturationBoost)
//        highlight = highlight.withSaturationDelta(depthFactor * saturationBoost * 1.5)
//        
//        // 更强烈的明暗对比
//        baseColor = baseColor.withBrightnessDelta(-depthFactor * baseDarkening)
//        highlight = highlight.withBrightnessDelta(depthFactor * highlightBrightening)
//        
//        if let gradientLayer = layer as? CAGradientLayer {
//            // 2. 优化渐变配置
//            gradientLayer.colors = [
//                baseColor.cgColor,
//                highlight.cgColor,  // 核心高光
//                baseColor.cgColor
//            ]
//            
//            // 更窄的高光区域 (仅占10%)
//            gradientLayer.locations = [0.45, 0.5, 0.55] as [NSNumber]
//            
//            // 3. 增强动画效果
//            let animationGroup = CAAnimationGroup()
//            
//            // 位置动画 - 快速移动的高光
//            let positionAnimation = CABasicAnimation(keyPath: "locations")
//            positionAnimation.fromValue = [0.0, 0.05, 0.1] as [NSNumber]
//            positionAnimation.toValue = [0.9, 0.95, 1.0] as [NSNumber]
//            
//            // 颜色动画 - 高光峰值亮度变化
//            let colorAnimation = CABasicAnimation(keyPath: "colors")
//            colorAnimation.fromValue = [
//                baseColor.cgColor,
//                highlight.withBrightnessDelta(0.2).cgColor, // 峰值更亮
//                baseColor.cgColor
//            ]
//            colorAnimation.toValue = gradientLayer.colors
//            
//            animationGroup.animations = [positionAnimation, colorAnimation]
//            animationGroup.duration = 1.2
//            animationGroup.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
//            animationGroup.repeatCount = .infinity
//            animationGroup.autoreverses = true
//            
//            gradientLayer.add(animationGroup, forKey: "skeletonPulse")
//            
//            gradientLayer.drawsAsynchronously = true
//            gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
//            gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
//        }
//        
//        // 添加轻微阴影增强深度感
//        layer.shadowColor = UIColor.black.withAlphaComponent(0.1).cgColor
//        layer.shadowOffset = CGSize(width: 0, height: depthFactor * 2)
//        layer.shadowRadius = depthFactor * 3
//        layer.shadowOpacity = Float(0.5 * depthFactor)
//        
//        layer.cornerRadius = view.layer.cornerRadius
//        layer.masksToBounds = false // 允许阴影显示
//    }
    
    private func removeAllSkeletons() {
        for (_, layer) in skeletonLayers {
            layer.removeFromSuperlayer()
            layerPool.enqueueLayer(layer)
        }
        skeletonLayers.removeAll()
    }
    
    private func startAnimations() {
        let animation = CABasicAnimation(keyPath: "locations")
        animation.fromValue = [-1.0, -0.5, 0.0]
        animation.toValue = [1.0, 1.5, 2.0]
        animation.duration = Constants.animationDuration
        animation.repeatCount = .infinity
        animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        
        // 分层动画偏移，避免所有动画同时开始
        for (index, layer) in skeletonLayers.values.enumerated() {
            let delay = 0.15 * Double(index % 3)
            DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                layer.add(animation, forKey: "skeletonWave")
            }
        }
    }
    
    private func stopAnimations() {
        skeletonLayers.values.forEach { $0.removeAnimation(forKey: "skeletonWave") }
    }

}
